﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using SharedGenomics.Workbench.Core;
using SharedGenomics.Workbench.PresentationModel;
using SharedGenomics.Workbench.Views;
using SharedGenomics.Core;
using SharedGenomics.Domain;
using SharedGenomics.Domain.Builders;
using SharedGenomics.DataTransfer;

namespace SharedGenomics.Workbench.Presenters
{
    public class DataFilterParametersPresenter : Presenter
    {
        public DataFilterParametersPresenter(IDataFilterParametersView view, CategoryFilterSetPresenter categoricalFiltersPresenter)
            : base(view)
        {
            //register for view events
            view.ApplyFiltersClicked += new EventHandler(this.View_ApplyFiltersClicked);

            //create presentation transfer object and set on view
            this.PTO = new FilterParametersPTO()
            {
                ApplyGenoFilter = true,
                ApplyHardyWeinbergFilter = true,
                ApplyMindFilter = true,
                MinGenotypingRate = "0.15",
                MinIndividualMissingess = "0.15",
                MinHardyWeinbergP = "0.001",
                MinMAF = "0.05"
            };

            view.PTO = this.PTO;
            this.PTO.ValidationChanged += new EventHandler<ValidationErrorsNotificationEventArgs>(this.PTO_ValidationChanged);

            //set private members
            this.FilterView = view;
            this.CategoryFiltersPresenter = categoricalFiltersPresenter;
        }

        private void PTO_ValidationChanged(object sender, ValidationErrorsNotificationEventArgs e)
        {
            this.View.ValidationErrors = e.ValidationErrors;
        }

        private void View_ApplyFiltersClicked(object sender, EventArgs e)
        {
            FilterParameterSetInfo parameters;
            if (this.TryCreateParameterSet(out parameters))
            {
                this.FilterStarted.Raise(this, new DataFilterEventArgs(parameters));
            }
        }

        public void ClearFilters()
        {
            this.CategoryFiltersPresenter.ClearFilters();
        }

        public bool TryCreateParameterSet(out FilterParameterSetInfo parameterSet)
        {
            //validate PTO
            if (this.PTO.Validate())
            {
                var pto = this.PTO;

                var builder = new FilterParameterSetBuilder()
                    .WithIndividualMissingness(pto.ApplyMindFilter ? decimal.Parse(pto.MinIndividualMissingess) : (decimal?)null)
                    .WithSnpMissingness(pto.ApplyGenoFilter ? decimal.Parse(pto.MinGenotypingRate) : (decimal?)null)
                    .WithMAF(decimal.Parse(pto.MinMAF))
                    .WithHardyWeinberg(pto.ApplyHardyWeinbergFilter ? decimal.Parse(pto.MinHardyWeinbergP) : (decimal?)null, pto.SelectedPhenotypeColumn);

                //add category filters
                this.CategoryFiltersPresenter.CategoricalFilters.ForEach(kvp =>
                {
                    builder.AddCategoricalFilter(kvp.Key, kvp.Value);
                });
                
                //TODO: validate!

                parameterSet = builder.Build();
                return true;
            }
            else
            {
                parameterSet = null;
                return false;
            }
        }

        public FileSchema Schema
        {
            set
            {
                this.CategoryFiltersPresenter.Schema = value;
                this.CategoryFiltersPresenter.AddCategoryFilter();

                this.PTO.PhenotypeColumns = value.PhenotypeColumns.Select(c => c.ToValueDisplayItem()).ToArray();
            }
        }

        public FileSetDataDistributionSummary DataDistribution
        {
            set { this.PTO.DataDistributionSummary = value; }
        }

        public event EventHandler<DataFilterEventArgs> FilterStarted;

        public bool CanFilter
        {
            get { return this.FilterView.IsApplyFiltersEnabled; }
            set { this.FilterView.IsApplyFiltersEnabled = value; }
        }

        private IDataFilterParametersView FilterView { get; set; }
        private FilterParametersPTO PTO { get; set; }

        [Region("CategoricalFilters")]
        public CategoryFilterSetPresenter CategoryFiltersPresenter { get; private set; }
    }
}
